菜单国际化实践:注意特殊情况defineXXX
在基于文件路由的项目中使用 definePage 和 defineOptions 等 Vue 宏时,需要注意一些特殊情况。这些宏在编译时处理,不受运行时逻辑控制,因此有些"看起来应该工作"的写法实际上会出错。
definePage 的限制
限制一:不能使用变量
// 错误:不能使用变量
const title = 'menu.home'
definePage({
meta: { title },
})
// 正确:必须使用字面量
definePage({
meta: { title: 'menu.home' },
})
typescript
definePage 是编译时宏,Unplugin Vue Router 在编译阶段提取 meta 信息,此时变量还未求值。
限制二:不能使用函数调用
// 错误:不能调用函数
definePage({
meta: { title: t('menu.home') },
})
// 正确:存储 i18n key
definePage({
meta: { title: 'menu.home' },
})
typescript
翻译(t())必须在运行时执行,不能在编译时宏中调用。
限制三:不能使用动态 key
// 错误:不能使用动态 key
const key = 'home'
definePage({
meta: { [`menu.${key}`]: true },
})
// 正确:使用静态 key
definePage({
meta: { title: 'menu.home' },
})
typescript
defineOptions 的使用
defineOptions 用于设置组件选项(如 name),在某些编译器版本中需要注意:
defineOptions({
name: 'PagesTableBasic',
})
typescript
如果同时使用了 definePage,确保两者的顺序不会导致编译冲突。通常 definePage 放在文件顶部,defineOptions 放在 script setup 区域。
i18n key 的命名规范
推荐使用层级化的 key 命名,方便管理和查找:
{
"menu": {
"home": "首页",
"about": "关于我们",
"components": {
"title": "组件示例",
"icon": "图标列表",
"notice": "消息通知"
}
}
}
json
对应的 i18n key:
menu.home → 首页
menu.components.title → 组件示例
text
处理没有 i18n key 的情况
某些页面可能没有设置 i18n key(如第三方页面),需要在菜单渲染时做兼容:
function getMenuTitle(meta: RootMeta): string {
if (!meta?.title) return ''
// 如果 title 是 i18n key(包含点号),则翻译
if (meta.title.includes('.')) {
return t(meta.title)
}
// 否则直接返回
return meta.title
}
typescript
本节小结
- definePage 限制:编译时宏,只能使用字面量,不能使用变量、函数调用或动态 key。
- i18n key 命名:使用层级化命名(
menu.home、menu.components.title)。 - 兼容处理:菜单渲染时判断 title 是否为 i18n key,分别处理翻译和直接显示。
↑